#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import random
import json
from Crypto.Cipher import AES
from binascii import a2b_hex
from handle.handler import BasicHandler
from download.sub.sycm import SycmDownloader
from analyze.analyzer import JsonAnalyzer
from store.sub.sycm import SycmWordStore
from public.util import run_status

import logging
import traceback


class SycmWordHandler(BasicHandler):
    def __init__(self, config):
        super(SycmWordHandler, self).__init__(config)
        self.mdb = config['mdb']
        self.mdb_excute_num = 0
        self.hash_key = '{}_cookie_hash'.format(self.name)
        # 密钥
        self.password = self.rds.hget(self.hash_key, 'password').encode('utf-8')
        # aes解密 偏移量
        self.offset = self.rds.hget(self.hash_key, 'offset').encode('utf-8')
        # 去掉补齐的字符
        self.un_pad = lambda s: s[0:-ord(s[-1])]

    def decrypt(self, text):
        b_data = bytes(text, encoding="utf-8")
        cryptor = AES.new(self.password, AES.MODE_CBC, self.offset)
        plain_bytes = cryptor.decrypt(a2b_hex(b_data))
        plain_text = bytes.decode(plain_bytes)
        return self.un_pad(plain_text)

    def get_downloader(self):
        return SycmDownloader(self.config)

    def get_analyzer(self):
        return JsonAnalyzer()

    def get_store(self):
        return SycmWordStore(self.config)

    def duplicated_key(self, task):
        return 'duplicated:{}:{}'.format(self.name, task['params']['keyword'])

    def sleep(self):
        sleep_time = self.rds.hget(self.hash_key, 'sleep_time')
        if sleep_time is None:
            return
        seconds = int(sleep_time)
        min_second = seconds - 10 if seconds - 10 > 0 else 0
        max_second = seconds + 10
        sleep_sec = random.randint(min_second, max_second)
        for i in range(sleep_sec):
            if i % 10 == 0:
                logging.info('sleep {} seconds for next task, {} seconds left...'.format(sleep_sec, sleep_sec-i))
            time.sleep(1)

    def save(self, result, task):
        try:
            data = result.get('data', '')
            if len(data) == 0:
                logging.error('unexpect response {}'.format(result))
                return run_status['except']
            des_text = self.decrypt(data)
            word_msg_list = json.loads(des_text)
            if len(word_msg_list) == 0:
                logging.warning('unexpect data {}'.format(result))
                return run_status['except']
            for word_msg in word_msg_list:
                word_msg['snatch_day'] = task['snatch_day']
                word_msg['searchword'] = task['params']['keyword']
                self.store.set(self.store.table, word_msg)
                self.mdb_excute_num += 1
            if self.mdb_excute_num > 0:
                self.mdb.commit()
                logging.info('download {} success, res {}'.format(task['params']['keyword'], len(word_msg_list)))
        except Exception as e:
            logging.error(e)
            logging.error(traceback.format_exc())
            return run_status['except']
        self.sleep()
        return run_status['success']
